package com.gbr.client.view;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.util.Callback;

import com.gbr.application.model.Capture;
import com.gbr.application.model.Frame;
import com.gbr.client.presentation.IDesktopPresentation;

public class FrameListDelegate implements PropertyChangeListener {
    private IDesktopPresentation  presentation = null;
    private ListView<Frame>       listView     = null;
    private ObservableList<Frame> data         = null;

    public FrameListDelegate(IDesktopPresentation prez) {
        presentation = prez;
        data = FXCollections.observableArrayList();
        presentation.addPropertyChangeListener(this);
    }

    public ListView<Frame> getList() {
        listView = new ListView<>(data);
        listView.setOrientation(Orientation.HORIZONTAL);
        listView.setCellFactory(new Callback<ListView<Frame>, ListCell<Frame>>() {
            @Override
            public ListCell<Frame> call(ListView<Frame> list) {
                return new FrameCell();
            }
        });
        listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Frame>() {
            @Override
            public void changed(ObservableValue<? extends Frame> value, Frame oldValue, Frame newValue) {
                presentation.changeFrameSelection(newValue, oldValue);
            }
        });
        return listView;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        String property = evt.getPropertyName();
        if (property.equals(IDesktopPresentation.FRAME_SELECTION_CHANGED)) {
            final Frame newValue = (Frame) evt.getNewValue();
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    listView.getSelectionModel().select(newValue);
                }
            });
        } else if (property.equals(IDesktopPresentation.CAPTURE_SELECTION_CHANGED)) {
            final Capture newValue = (Capture) evt.getNewValue();
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    listView.getItems().setAll(newValue.getFrames());
                }
            });
        }
    }

    class FrameCell extends ListCell<Frame> {
        @Override
        public void updateItem(Frame frame, boolean empty) {
            super.updateItem(frame, empty);
            if (frame != null) {
                VBox vBox = new VBox();
                vBox.setPadding(new Insets(2.5));
                vBox.setSpacing(5);
                vBox.setAlignment(Pos.CENTER);
                vBox.getChildren().add(new Text("Frame"));

                ImageView imageView = new ImageView(SwingFXUtils.toFXImage(frame.getImage(), null));
                imageView.setFitWidth(125);
                imageView.setPreserveRatio(true);
                imageView.setSmooth(true);
                imageView.setCache(true);

                VBox.setVgrow(imageView, Priority.ALWAYS);
                vBox.getChildren().add(imageView);

                HBox hBox = new HBox();
                hBox.getChildren().add(new Text("Delay: "));
                TextField field = new TextField("" + frame.getDelay());
                hBox.getChildren().add(field);
                vBox.getChildren().add(hBox);

                setGraphic(vBox);
            }
        }
    }
}
